﻿using System;
using System.Collections.Generic;
using System.IO.Ports;

namespace RM.Weighing
{
    /// <summary>
    /// 串口服务
    /// </summary>
    public class SerialPortService
    {
        #region 内部变量
        /// <summary>
        /// 端口名称
        /// </summary>
        public string PortName { get; set; }

        /// <summary>
        /// 波特率
        /// </summary>
        public SerialPortBaudRateList BaudRate { get; set; }

        /// <summary>
        /// 数据位
        /// </summary>
        public SerialPortDataBitList DataBits { get; set; }

        /// <summary>
        /// 停止位 默认1
        /// </summary>
        public StopBits StopBits { get; set; } = StopBits.One;

        /// <summary>
        /// 奇偶校验 默认0
        /// </summary>
        public Parity Parity { get; set; } = Parity.None;


        private SerialPort _serialPort = new SerialPort();

        /// <summary>
        /// 接收的数据
        /// </summary>
        public event Action<List<byte>> DataReceived;

        /// <summary>
        /// 接收的错误
        /// </summary>
        public event SerialErrorReceivedEventHandler ErrorReceived;

        private List<byte> _database = new List<byte>();
        #endregion

        #region 构造函数

        private void BindingOperation()
        {
            _serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
            _serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(SerialPort_ErrorReceived);
        }

        /// <summary>
        /// 参数构造函数
        /// </summary>
        /// <param name="portName">端口名称</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>
        /// <param name="parity">奇偶校验</param>
        public SerialPortService(string portName, SerialPortBaudRateList baudRate, SerialPortDataBitList dataBits, StopBits stopBits, Parity parity)
        {
            PortName = portName;
            BaudRate = baudRate;
            DataBits = dataBits;
            StopBits = stopBits;
            Parity = parity;
            BindingOperation();
        }

        /// <summary>
        /// 参数构造函数
        /// </summary>
        /// <param name="portName">端口名称</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="dataBits">数据位</param>
        public SerialPortService(string portName, SerialPortBaudRateList baudRate, SerialPortDataBitList dataBits)
        {
            PortName = portName;
            BaudRate = baudRate;
            DataBits = dataBits;
            BindingOperation();
        }

        #endregion

        #region 事件函数
        /// <summary>
        /// 关闭串口
        /// </summary>
        public void Close()
        {
            if (_serialPort.IsOpen) _serialPort.Close();
        }
        /// <summary>
        /// 打开串口
        /// </summary>
        public void Open()
        {
            Close();
            _serialPort.PortName = PortName;
            _serialPort.BaudRate = (int)BaudRate;
            _serialPort.Parity = Parity;
            _serialPort.StopBits = StopBits;
            _serialPort.DataBits = (int)DataBits;

            _serialPort.Open();

        }

        /// <summary>
        /// 串口是否打开
        /// </summary>
        /// <returns>若已打开则结果为 true，反之为 false</returns>
        public bool IsOpen()
        {
            return _serialPort.IsOpen;
        }
        /// <summary>
        /// 串行端口接收数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">串行数据接收事件参数</param>
        public void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (!(_serialPort.IsOpen)) Open();


            Byte[] receivedData = new Byte[_serialPort.BytesToRead];        //创建接收字节数组
            _serialPort.Read(receivedData, 0, receivedData.Length);         //读取数据

            //触发整条记录的处理
            if (DataReceived != null)
            {
                _database.AddRange(receivedData);
                DataReceived(_database);
            }
        }

        /// <summary>
        /// 错误事件接收
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            if (ErrorReceived != null)
            {
                ErrorReceived(sender, e);
            }
        }
        #endregion


        #region 写入数据

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="buffer">写入端口的字节数组</param>
        public void Write(byte[] buffer)
        {
            bool isOpen = _serialPort.IsOpen;
            try
            {
                if (!isOpen) Open();
                _serialPort.Write(buffer, 0, buffer.Length);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (!isOpen) Close();
            }
        }

        #endregion

    }
}
